using System.Text.Json;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Ocelot.Configuration.File;

namespace Beauty.Net.Ocelot.Core;

/// <summary>
/// Ocelot配置管理器实现
/// </summary>
public class OcelotConfigurationManager : IOcelotConfigurationManager
{
    private readonly ILogger<OcelotConfigurationManager> _logger;
    private readonly OcelotOptions _options;
    private readonly Beauty.Net.Ocelot.Core.IOcelotBuilder _ocelotBuilder;
    private FileConfiguration _currentConfiguration = new();
    private readonly object _lock = new();
    
    /// <summary>
    /// 构造函数
    /// </summary>
    public OcelotConfigurationManager(
        ILogger<OcelotConfigurationManager> logger,
        IOptions<OcelotOptions> options,
        IOcelotBuilder ocelotBuilder)
    {
        _logger = logger;
        _options = options.Value;
        _ocelotBuilder = ocelotBuilder;
    }
    
    /// <summary>
    /// 获取当前配置
    /// </summary>
    public async Task<FileConfiguration> GetConfigurationAsync(CancellationToken cancellationToken = default)
    {
        lock (_lock)
        {
            if (_currentConfiguration is null)
            {
                _currentConfiguration = LoadConfigurationFromFile();
            }
            return _currentConfiguration;
        }
    }
    
    /// <summary>
    /// 更新配置
    /// </summary>
    public async Task<bool> UpdateConfigurationAsync(FileConfiguration configuration, CancellationToken cancellationToken = default)
    {
        try
        {
            lock (_lock)
            {
                _currentConfiguration = configuration;
                SaveConfigurationToFile(configuration);
            }
            
            _logger.LogInformation("Ocelot配置已更新");
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "更新Ocelot配置失败");
            return false;
        }
    }
    
    /// <summary>
    /// 添加路由
    /// </summary>
    public async Task<bool> AddRouteAsync(FileRoute route, CancellationToken cancellationToken = default)
    {
        try
        {
            var configuration = await GetConfigurationAsync(cancellationToken);
            
            if (!configuration.Routes.Any(r => r.Key == route.Key))
            {
                configuration.Routes.Add(route);
                return await UpdateConfigurationAsync(configuration, cancellationToken);
            }
            
            _logger.LogWarning("路由已存在: {RouteKey}", route.Key);
            return false;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "添加路由失败: {RouteKey}", route.Key);
            return false;
        }
    }
    
    /// <summary>
    /// 更新路由
    /// </summary>
    public async Task<bool> UpdateRouteAsync(string routeKey, FileRoute route, CancellationToken cancellationToken = default)
    {
        try
        {
            var configuration = await GetConfigurationAsync(cancellationToken);
            var existingRouteIndex = configuration.Routes.FindIndex(r => r.Key == routeKey);
            
            if (existingRouteIndex >= 0)
            {
                // 确保更新的路由使用相同的Key
                route.Key = routeKey;
                configuration.Routes[existingRouteIndex] = route;
                return await UpdateConfigurationAsync(configuration, cancellationToken);
            }
            
            _logger.LogWarning("未找到路由: {RouteKey}", routeKey);
            return false;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "更新路由失败: {RouteKey}", routeKey);
            return false;
        }
    }
    
    /// <summary>
    /// 删除路由
    /// </summary>
    public async Task<bool> DeleteRouteAsync(string routeKey, CancellationToken cancellationToken = default)
    {
        try
        {
            var configuration = await GetConfigurationAsync(cancellationToken);
            var existingRoute = configuration.Routes.FirstOrDefault(r => r.Key == routeKey);
            
            if (existingRoute != null)
            {
                configuration.Routes.Remove(existingRoute);
                return await UpdateConfigurationAsync(configuration, cancellationToken);
            }
            
            _logger.LogWarning("未找到路由: {RouteKey}", routeKey);
            return false;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "删除路由失败: {RouteKey}", routeKey);
            return false;
        }
    }
    
    /// <summary>
    /// 重新加载配置
    /// </summary>
    public async Task<bool> ReloadConfigurationAsync(CancellationToken cancellationToken = default)
    {
        try
        {
            lock (_lock)
            {
                _currentConfiguration = LoadConfigurationFromFile();
            }
            
            _logger.LogInformation("Ocelot配置已重新加载");
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "重新加载Ocelot配置失败");
            return false;
        }
    }
    
    /// <summary>
    /// 导出配置到文件
    /// </summary>
    public async Task<bool> ExportConfigurationAsync(string filePath, CancellationToken cancellationToken = default)
    {
        try
        {
            var configuration = await GetConfigurationAsync(cancellationToken);
            var json = JsonSerializer.Serialize(configuration, new JsonSerializerOptions { WriteIndented = true });
            await File.WriteAllTextAsync(filePath, json, cancellationToken);
            
            _logger.LogInformation("配置已导出到: {FilePath}", filePath);
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "导出配置失败: {FilePath}", filePath);
            return false;
        }
    }
    
    /// <summary>
    /// 从配置选项创建Ocelot配置
    /// </summary>
    public FileConfiguration CreateConfigurationFromOptions(List<ApiRouteOptions> routes)
    {
        var configuration = new FileConfiguration
        {
            Routes = new List<FileRoute>(),
            GlobalConfiguration = new FileGlobalConfiguration
            {
                BaseUrl = string.Empty,
                RequestIdKey = "RequestId",
                ServiceDiscoveryProvider = _options.EnableConsulServiceDiscovery ? new FileServiceDiscoveryProvider
                {
                    Host = _options.ConsulDiscovery.Host,
                    Port = _options.ConsulDiscovery.Port,
                    Token = _options.ConsulDiscovery.Token,
                    Namespace = _options.ConsulDiscovery.Namespace,
                    ConfigurationKey = "ServiceDiscoveryProvider",
                    Type = "Consul"
                } : null
            }
        };
        
        // 转换路由配置
        foreach (var routeOption in routes)
        {
            var route = new FileRoute
            {
                Key = routeOption.RouteKey,
                UpstreamPathTemplate = routeOption.UpstreamPathTemplate,
                UpstreamHttpMethod = routeOption.UpstreamHttpMethod,
                DownstreamPathTemplate = routeOption.DownstreamPathTemplate,
                DownstreamScheme = routeOption.DownstreamScheme,
                LoadBalancerOptions = new FileLoadBalancerOptions
                {
                    Type = routeOption.LoadBalancerOptions
                }
            };
            
            // 配置服务发现
            if (!string.IsNullOrEmpty(routeOption.ServiceName))
            {
                route.ServiceName = routeOption.ServiceName;
                // 在新版本的Ocelot中，UseServiceDiscovery可能是通过ServiceName的存在来推断的
                // 这里只设置必要的属性
            }
            else
            {
                // 如果没有服务名，则使用下游主机配置
                route.DownstreamHostAndPorts = new List<FileHostAndPort>();
            }
            
            // 配置速率限制
            if (routeOption.EnableRateLimiting)
            {
                // 配置速率限制（适配新版本的Ocelot属性）
                route.RateLimitOptions = new FileRateLimitRule
                {
                    ClientWhitelist = routeOption.RateLimitOptions.ClientWhitelist,
                    Period = $"{routeOption.RateLimitOptions.PeriodSeconds}s",
                    // 使用与ocelot.json中匹配的属性名称
                    // PermitLimit和QueueLimit可能在新版本中已更改
                };
            }
            
            configuration.Routes.Add(route);
        }
        
        return configuration;
    }
    
    /// <summary>
    /// 从文件加载配置
    /// </summary>
    private FileConfiguration LoadConfigurationFromFile()
    {
        if (!File.Exists(_options.ConfigurationPath))
        {
            _logger.LogWarning("配置文件不存在，创建默认配置: {Path}", _options.ConfigurationPath);
            return CreateDefaultConfiguration();
        }
        
        try
        {
            var json = File.ReadAllText(_options.ConfigurationPath);
            return JsonSerializer.Deserialize<FileConfiguration>(json) ?? CreateDefaultConfiguration();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "读取配置文件失败: {Path}", _options.ConfigurationPath);
            return CreateDefaultConfiguration();
        }
    }
    
    /// <summary>
    /// 保存配置到文件
    /// </summary>
    private void SaveConfigurationToFile(FileConfiguration configuration)
    {
        try
        {
            var json = JsonSerializer.Serialize(configuration, new JsonSerializerOptions { WriteIndented = true });
            File.WriteAllText(_options.ConfigurationPath, json);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "保存配置文件失败: {Path}", _options.ConfigurationPath);
            throw;
        }
    }
    
    /// <summary>
    /// 创建默认配置
    /// </summary>
    private FileConfiguration CreateDefaultConfiguration()
    {
        return new FileConfiguration
        {
            Routes = new List<FileRoute>(),
            GlobalConfiguration = new FileGlobalConfiguration
            {
                BaseUrl = string.Empty,
                RequestIdKey = "RequestId",
                ServiceDiscoveryProvider = _options.EnableConsulServiceDiscovery ? new FileServiceDiscoveryProvider
                {
                    Host = _options.ConsulDiscovery.Host,
                    Port = _options.ConsulDiscovery.Port,
                    Type = "Consul"
                } : null
            }
        };
    }
}

/// <summary>
/// Ocelot构建器接口
/// </summary>
public interface IOcelotBuilder
{
    /// <summary>
    /// 服务集合
    /// </summary>
    IServiceCollection Services { get; }
}

/// <summary>
/// Ocelot构建器实现
/// </summary>
public class OcelotBuilder : IOcelotBuilder
{
    /// <summary>
    /// 构造函数
    /// </summary>
    public OcelotBuilder(IServiceCollection services)
    {
        Services = services;
    }
    
    /// <summary>
    /// 服务集合
    /// </summary>
    public IServiceCollection Services { get; }
}